﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Paladyne.FileSearch.Core;

namespace Paladyne.FileSearch.UI
{
    /// <summary>
    /// Represents a concrete implementation of ISearcher
    /// </summary>
    internal class FileSearcher : ISearcher
    {
        private readonly IFileEnumerator _fileEnumerator;

        public FileSearcher() : this(new BreadthFirstFileEnumerator())
        {
        }

        public FileSearcher(IFileEnumerator fileEnumerator)
        {
            _fileEnumerator = fileEnumerator;
        }

        /// <summary>
        /// Check if processed file satisfies all conditions
        /// </summary>
        /// <param name="file"></param>
        /// <param name="conditions"></param>
        /// <returns></returns>
        private bool CheckFile(FileInfo file, IEnumerable<Predicate<FileInfo>> conditions)
        {
            bool result = conditions.All(condition => condition(file));
            if (result && SearchModule != null)
                result = SearchModule.Check(file);
            return result;
        }

        #region Implementation of ISearcher

        public ISearchModule SearchModule { get; set; }

        /// <summary>
        /// Perform a sfile earch with specified parameters and conditions
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="conditions"></param>
        /// <returns></returns>
        public IEnumerable<FileInfo> Search(SearchParameters parameters, IEnumerable<Predicate<FileInfo>> conditions)
        {
            if (!Directory.Exists(parameters.DirectoryName))
                throw new DirectoryNotFoundException("Search path not found");

            foreach (
                FileInfo file in
                    _fileEnumerator.Enumerate(new DirectoryInfo(parameters.DirectoryName),
                                              parameters.SearchInSubdirectories))
            {
                if (CheckFile(file, conditions))
                    yield return file;
            }
        }

        #endregion
    }
}